/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @file nfa_rw.h
 * @brief 读卡相关API定义
 */

#ifndef _NFA_RW_H_
#define _NFA_RW_H_

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "nci_feature.h"
#if IS_FEATURE_ON(NCI_FEATURE_RW)

#include "nfa_base.h"
#include "nfa_utils.h"

#define NCI_RW_MAX_UID_LEN 11
#define NCI_RW_MAX_TECH_LIST_LEN 4

#define NCI_RW_MAX_POLL_DATA_LEN 10
#define NCI_RW_MAX_ACT_DATA_LEN 50

/** @brief 卡片类型，一张卡片可以同时支持多个类型 */
typedef uint8_t tNCI_RW_TAG_TYPE;
/** @brief 未知类型 */
#define NCI_RW_TAG_TYPE_UNKNOWN 0
/**
 * @brief TypeA类型，NFC-A卡会包含此类型
 * @example T1T、T2T、T4TA、M1卡
 */
#define NCI_RW_TAG_TYPE_A 1
/**
 * @brief TypeB类型，NFC-B卡会包含此类型
 * @example T4TB、CI卡
 */
#define NCI_RW_TAG_TYPE_B 2
/**
 * @brief ISO-DEP类型, 支持IsoDep协议的卡会包含此类型
 * @example T4TA、T4TB
 */
#define NCI_RW_TAG_TYPE_ISO_DEP 3
/**
 * @brief NfcF类型，NFC-F卡会包含此类型
 * @example T3T卡
 */
#define NCI_RW_TAG_TYPE_F 4
/**
 * @brief NfcV类型，NFC-V卡会包含此类型
 * @example T5T卡
 */
#define NCI_RW_TAG_TYPE_V 5
/**
 * @brief Ndef类型，卡片中包含NDEF数据的情况下会包含此类型
 * @note 一般是通过nfa_rw_ndef_detect()、nfa_rw_ndef_read()函数确定卡片是否有NDEF数据
 */
#define NCI_RW_TAG_TYPE_NDEF 6
/**
 * @brief NdefFormatable类型，卡片中不包含NDEF数据但是可以格式化的情况下会包含此类型
 * @note 一般通过nfa_rw_is_ndef_formatable()函数确定卡片是否可以格式化
 */
#define NCI_RW_TAG_TYPE_NDEF_FORMATABLE 7
/**
 * @brief M1类型，M1卡会包含此类型
 * @example NfcA M1协议卡
 */
#define NCI_RW_TAG_TYPE_M1 8
/**
 * @brief MUL类型
 * @example NfcA T2T协议MUL卡
 */
#define NCI_RW_TAG_TYPE_MUL 9
/**
 * @brief Kovio类型
 * @example NfcA Kovio卡
 */
#define NCI_RW_TAG_TYPE_KOVIO 10

#define NCI_RW_TAG_TYPE_MAX 11

/** @brief 读卡事件类型 */
typedef enum {
    /** @brief 检测到卡片 */
    NCI_RW_EVT_TAG_DETECTED = 0,
    /** @brief 卡片离场 */
    NCI_RW_EVT_TAG_LOSTED,
    /** @brief 记录事件数量 */
    NCI_RW_EVT_MAX,
} tNCI_RW_EVT;

/** @brief 卡片POLL DATA */
typedef struct {
    uint8_t len;
    uint8_t data[NCI_RW_MAX_POLL_DATA_LEN];
} tNCI_RW_POLL_DATA;
/** @brief 卡片ACTIVATE DATA */
typedef struct {
    uint8_t len;
    uint8_t data[NCI_RW_MAX_ACT_DATA_LEN];
} tNCI_RW_ACT_DATA;

/**
 * @brief 卡片信息结构体
 */
typedef struct {
    /** @brief 卡片UID */
    uint8_t uid[NCI_RW_MAX_UID_LEN];
    /** @brief UID长度 */
    uint8_t uid_len;
    /** @brief 卡片包含的TECH数量，是下面disc_ids等数组的大小 */
    uint8_t tech_size;
    /** @brief 当前激活的卡片TECH数组索引 */
    uint8_t index;
    /** @brief DISCOVERY ID数组 */
    tNCI_RF_DISCOVERY_ID disc_ids[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片支持的卡片协议列表 */
    tNCI_RF_PROTOCOL protocols[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片支持的卡片RF接口列表 */
    tNCI_RF_INTERFACE interfaces[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片支持的类型列表 */
    tNCI_RW_TAG_TYPE tag_types[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片的tech激活参数列表 */
    tNCI_RF_TECH_PARAMS tech_params[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片的act激活参数列表 */
    tNCI_RF_ACT_PARAMS act_params[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片的poll data参数列表 */
    tNCI_RW_POLL_DATA poll_data[NCI_RW_MAX_TECH_LIST_LEN];
    /** @brief 此卡片的act data参数列表 */
    tNCI_RW_ACT_DATA act_data[NCI_RW_MAX_TECH_LIST_LEN];
} tNCI_RW_TAG;

/** @brief NDEF读写模式 */
typedef enum {
    /** @brief 只读 */
    NCI_RW_NDEF_MODE_READ_ONLY = 1,
    /** @brief 可读可写 */
    NCI_RW_NDEF_MODE_READ_WRITE = 2,
    /** @brief 未知 */
    NCI_RW_NDEF_MODE_UNKNOWN = 3,
} tNCI_RW_NDEF_MODE;

/** @brief NDEF类型 */
typedef enum {
    NCI_RW_NDEF_TYPE_UNKNOWN = -1,
    NCI_RW_NDEF_TYPE1_TAG = 1,
    NCI_RW_NDEF_TYPE2_TAG = 2,
    NCI_RW_NDEF_TYPE3_TAG = 3,
    NCI_RW_NDEF_TYPE4_TAG = 4,
    NCI_RW_NDEF_TYPE5_TAG = 5,
    NCI_RW_NDEF_TYPE_M1_TAG = 101,
} tNCI_RW_NDEF_TYPE;

/** @brief NDEF信息 */
typedef struct {
    /** @brief 当前NDEF数据的长度 */
    uint32_t curr_size;
    /** @brief 卡片支持写入的最大NDEF数据长度 */
    uint32_t max_size;
    /** @brief NDEF读写模式 */
    tNCI_RW_NDEF_MODE mode;
} tNCI_RW_NDEF_INFO;

/**
 * @brief 读卡事件回调函数
 *
 * @param event 事件类型
 * @param p_tag 标签信息，如果event为NCI_RW_EVT_TAG_DETECTED，则此参数有效
 */
typedef void(*tNCI_RW_CBACK)(tNCI_RW_EVT event, const tNCI_RW_TAG *p_tag);
/**
 * @brief 设置指定类型卡片的指令传输超时时间
 *
 * @param tag_type 要设置的卡片类型
 * @param timeout 超时时间，单位ms
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_set_transceive_timeout(tNCI_RW_TAG_TYPE tag_type, uint32_t timeout);
/**
 * @brief 重置所有指令传输超时时间
 */
void nfa_rw_reset_all_transceive_timeout(void);
/**
 * @brief 获取指定类型卡片的指令传输超时时间
 *
 * @param tag_type 要获取的卡片类型
 *
 * @return 返回超时时间，单位ms
 */
uint32_t nfa_rw_get_transceive_timeout(tNCI_RW_TAG_TYPE tag_type);
/**
 * @brief 连接指定index的技术
 *
 * @note index需要小于tag的tech_size
 *
 * @param index 要连接的TECH索引
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_connect(uint8_t index);
/**
 * @brief 重新连接当前连接的技术
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_reconnect();
/**
 * @brief 断开当前卡片连接
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_disconnect();
/**
 * @brief 检查卡片是否在场
 *
 * @return 在场返回NCI_STATUS_OK，不在场返回其他错误码
 */
tNCI_STATUS nfa_rw_presence_check();
/**
 * @brief 发送命令给卡片
 *
 * @param[in] p_data 命令数据指针
 * @param[in] data_len 命令数据长度
 * @param[out] p_rsp 接受返回卡片响应数据的BUF
 *
 * @note 只有在函数返回成功时，p_rsp才有数据
 * @note 函数返回成功后，p_rsp需要由调用方管理，调用nfa_utils_free()释放
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_transceive(uint8_t *p_data, uint16_t data_len, tNCI_RSP *p_rsp);
/**
 * @brief 检查卡片是否包含NDEF数据
 *
 * @param[out] p_ndef_info 用于返回NDEF信息
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_ndef_detect(tNCI_RW_NDEF_INFO *p_ndef_info);
/**
 * @brief 读取NDEF数据
 *
 * @param[out] p_rsp 用于返回NDEF数据
 *
 * @note 需要先调用nfa_rw_ndef_detect()函数检查卡片是否包含NDEF数据
 * @note 只有在函数返回成功时，p_rsp才有数据
 * @note 函数返回成功后，p_rsp需要由调用方管理，调用nfa_utils_free()释放
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_ndef_read(tNCI_RSP *p_rsp);
/**
 * @brief 写入NDEF数据
 *
 * @note 需要先调用nfa_rw_ndef_detect()函数检查卡片是否包含NDEF数据
 *
 * @param p_data 需要写入的NDEF数据
 * @param data_len 需要写入的NDEF数据长度
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_ndef_write(uint8_t *p_data, uint32_t data_len);
/**
 * @brief 将卡片格式为NDEF格式
 *
 * @param p_key 格式化密钥
 * @param key_len 格式化密钥长度
 *
 * @note p_key和key_len只在卡片为M1类型时需要提供
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_ndef_format(uint8_t *p_key, uint8_t key_len);
/**
 * @brief 设置卡片为只读
 *
 * @note 本操作不可逆，请谨慎操作
 *
 * @param is_hard_lock 是否为硬锁定
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他错误码
 */
tNCI_STATUS nfa_rw_set_tag_read_only(bool is_hard_lock);
/**
 * @brief 判断卡片是否可格式化为NDEF
 *
 * @return 可以格式化成NDEF返回NCI_STATUS_OK，否则返回其他错误码
 */
tNCI_STATUS nfa_rw_is_ndef_formatable();
/**
 * @brief 通过Protocol和TechType获取NDEF类型
 *
 * @param protocol 协议类型
 * @param tag_type 技术类型
 *
 * @return NDEF类型，如果获取失败返回NCI_RW_NDEF_TYPE_UNKNOWN
 */
tNCI_RW_NDEF_TYPE nfa_rw_ndef_get_type(tNCI_RF_PROTOCOL protocol, tNCI_RW_TAG_TYPE tag_type);

/**
 * @brief 获取IsoDep协议最大传输长度
 *
 * @return IsoDep协议最大传输长度
 */
uint32_t nfa_rw_get_iso_dep_max_transceive_length();
/**
 * @brief 判断当前卡片是不是ultalight c卡片
 *
 * @return 如果是返回true，反之返回false
 */
bool nfa_rw_is_ultralight_c();
/**
 * @brief 获取读卡模块内部的锁
 *
 * @note 获取锁后，需要调用nfa_rw_release_lock()释放锁
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他
 */
tNCI_STATUS nfa_rw_request_lock();
/**
 * @brief 释放读卡模块内部的锁
 *
 * @note 需要先调用nfa_rw_request_lock()获取锁
 *
 * @return 成功返回NCI_STATUS_OK，失败返回其他
 */
tNCI_STATUS nfa_rw_release_lock();
/**
 * @brief 获取当前激活的标签
 *
 * @return 如果当前有激活的标签，则返回该标签指针，否则返回NULL
 */
tNCI_RW_TAG *nfa_rw_get_activated_tag();

#if IS_FEATURE_ON(NCI_FEATURE_NDEF_EXT)
/**
 * @brief 读取并添加NDEF类型到当前卡片
 *
 * @note 如果卡片没有NDEF数据但是支持格式化成NDEF会添加NCI_RW_TAG_TYPE_NDEF_FORMATABLE
 *
 * @param[out] p_ndef_rsp 用于接收读取到的NDEF数据，函数返回NCI_STATUS_OK时有效
 * @param[out] p_ndef_type 用于接收NDEF类型，函数返回NCI_STATUS_OK时有效
 * @param[out] p_ndef_mode 用于接收NDEF模式，函数返回NCI_STATUS_OK时有效
 *
 * @return 读取NDEF数据成功返回NCI_STATUS_OK，反之返回其他错误码
 */
tNCI_STATUS nfa_rw_ndef_find_and_add_tech(tNCI_RSP *p_ndef_rsp, tNCI_RW_NDEF_TYPE *p_ndef_type, tNCI_RW_NDEF_MODE *p_ndef_mode);
#endif // IS_FEATURE_ON(NCI_FEATURE_NDEF_EXT)

#if IS_FEATURE_ON(NCI_FEATURE_RW_EXT)

/** @brief 读卡Watchdog线程运行状态 */
typedef enum {
    /** @brief watchdog线程未运行 */
    NCI_RW_WDST_STOPED = 0,
    /** @brief 请求启动watchdog线程 */
    NCI_RW_WDST_REQUEST_START,
    /** @brief watchdog线程运行中 */
    NCI_RW_WDST_RUNNING,
    /** @brief watchdog线程暂停中 */
    NCI_RW_WDST_PAUSED,
    /** @brief 请求停止watchdog线程 */
    NCI_RW_WDST_REQUEST_STOP,
    /** @brief watchdog线程已经停止，但是还未调用join函数回收资源 */
    NCI_RW_WDST_STOPED_WAIT_JOIN,
} tNCI_RW_WDST;

/**
 * @brief 开启卡片在场检测watch dog线程
 *
 * @param presence_check_delay 检测时间周期，单位ms
 *
 * @return 开启线程成功返回NCI_STATUS_OK，反之返回其他错误码
 */
tNCI_STATUS nfa_rw_watch_dog_start(uint32_t presence_check_delay);
/**
 * @brief 停止卡片在场检测watch dog线程
 *
 * @return 停止线程成功返回NCI_STATUS_OK，反之返回其他错误码
 */
tNCI_STATUS nfa_rw_watch_dog_stop();
/**
 * @brief 设置卡片在场检测watch dog线程状态
 *
 * @param is_paused 是否暂停检测
 *
 * @return 设置成功返回NCI_STATUS_OK，反之返回其他错误码
 */
tNCI_STATUS nfa_rw_watch_dog_set_state(bool is_paused);

/**
 * @brief 获取卡片在场检测watch dog线程状态
 * @return 当前状态
 */
tNCI_RW_WDST nfa_rw_watch_dog_get_state();

#endif // IS_FEATURE_ON(NCI_FEATURE_RW_EXT)

#endif // IS_FEATURE_ON(NCI_FEATURE_RW)

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif // _NFA_RW_H_
